﻿/*
 * fixdstring.hpp
 *
 *  Created on: 2016年11月16日
 *      Author: Dylan.Gao
 */

#ifndef _DM_FIXDSTRING_HPP_
#define _DM_FIXDSTRING_HPP_

#include <dm/string/stringref.hpp>
#include <dm/types.hpp>
#include <string>
#include <cstring>
#include <iostream>

namespace dm{

template<dm::uint Size>
class CFixdString{
public:
	CFixdString();
	CFixdString( const char* str ){ *this = str; }
	CFixdString( const std::string& str ){ *this = str; }
	CFixdString( const CFixdString& str ){ *this = str; }

	CFixdString& operator=( const CFixdString& str );
	CFixdString& operator=( const char* str );
	volatile CFixdString& operator=( const char* str )volatile;
	inline CFixdString& operator=( const std::string& str ){
		return *this=str.c_str();
	}

	CFixdString& operator=( const std::string& str )volatile{
		return *this = str.c_str();
	}

	inline CFixdString& operator+=( const CFixdString& str ){
		return *this += str.m_b;
	}
	CFixdString& operator+=( const char* str );
	inline CFixdString& operator+=( const std::string& str ){
		return *this += str.c_str();
	}

	bool operator==( const CFixdString& str )const;
	bool operator==( const char* str )const;
	bool operator==( const std::string& str )const;

	bool operator!=( const CFixdString& str )const;
	bool operator!=( const char* str )const;
	bool operator!=( const std::string& str )const;

	bool operator<(const CFixdString& str) const;

	friend inline std::ostream& operator<<(std::ostream& ostr,const CFixdString<Size>& str ){
		return ostr<<str.c_str();
	}

	inline const char* c_str()const{
		return m_b;
	}

	inline char* str(){
		return m_b;
	}

	inline size_t len()const{
		return std::strlen(m_b);
	}

	inline void dump( char* buf,int l )const{
		dm::string::CStringRef(m_b).dump(buf,l);
	}

	static inline dm::uint maxSize(){
		return Size;
	}
private:
	char m_b[Size];
};

template<dm::uint Size>
CFixdString<Size>::CFixdString(){
	m_b[0] = '\0';
}

template<dm::uint Size>
CFixdString<Size>& CFixdString<Size>::operator =( const char* str ){
	dm::string::CStringRef(str).dumpSome(m_b,Size);
	return *this;
}

template<dm::uint Size>
volatile CFixdString<Size>& CFixdString<Size>::operator =( const char* str )volatile{
	dm::string::CStringRef(str).dumpSome(m_b,Size);
	return *this;
}

template<dm::uint Size>
CFixdString<Size>& CFixdString<Size>::operator=( const CFixdString<Size>& str ){
	if( str.m_b[0]=='\0' )
		m_b[0] = '\0';
	else {
#ifdef WIN32
		strcpy_s(m_b, Size, str.m_b);
#else
		std::strcpy(m_b, str.m_b);
#endif
	}

	return *this;
}

template<dm::uint Size>
CFixdString<Size>& CFixdString<Size>::operator +=( const char* str ){
	if( str!=NULL && str[0]!='\0' ){
		dm::uint p;
		for(p=0;p<Size;++p )
			if( m_b[p]=='\0' )
				break;

		dm::uint i = 0;
		for(;p<Size-1;++p ){
			if( str[i]!='\0' ){
				m_b[p] = str[i];
				++i;
			}else
				break;
		}

		m_b[p] = '\0';
	}

	return *this;
}

template<dm::uint Size>
bool CFixdString<Size>::operator ==( const CFixdString<Size>& str )const{
	if( str.m_b[0]=='\0' )
		return m_b[0]=='\0';

	if( m_b[0]==0 )
		return false;
	return std::strcmp(m_b,str.m_b)==0;
}

template<dm::uint Size>
bool CFixdString<Size>::operator ==( const char* str )const{
	if( str==NULL || str[0]=='\0' )
		return m_b[0]=='\0';

	if( m_b[0]==0 )
		return false;
	return std::strcmp(m_b,str)==0;
}

template<dm::uint Size>
bool CFixdString<Size>::operator ==( const std::string& str )const{
	if( str.length()==0 )
		return m_b[0]=='\0';

	if( m_b[0]==0 )
		return false;
	return std::strcmp(m_b,str.c_str())==0;
}

template<dm::uint Size>
bool CFixdString<Size>::operator !=( const CFixdString<Size>& str )const{
	if( str.m_b[0]=='\0' )
		return m_b[0]!='\0';

	if( m_b[0]==0 )
		return true;
	return std::strcmp(m_b,str.m_b);
}

template<dm::uint Size>
bool CFixdString<Size>::operator !=( const char* str )const{
	if( str==NULL || str[0]=='\0' )
		return m_b[0]!='\0';

	if( m_b[0]==0 )
		return true;
	return std::strcmp(m_b,str);
}

template<dm::uint Size>
bool CFixdString<Size>::operator !=( const std::string& str )const{
	if( str.length()==0 )
		return m_b[0]!='\0';

	if( m_b[0]==0 )
		return true;
	return std::strcmp(m_b,str.c_str());
}

template<dm::uint Size>
bool CFixdString<Size>::operator<(const CFixdString& str) const{
	if(strcmp(this->c_str(), str.c_str()) < 0){
		return true;
	}else{
		return false;
	}
}

}

#endif /* INCLUDE_DM_FIXDSTRING_HPP_ */
